#include <string>
#include <vector>

/* OPCODE */
#define RRQ 	1
#define DATA 	3
#define ACK 	4
#define ERROR 	5

/* ERROR CODES */
#define FILENOTFOUND 		1
#define ACCESSVIOLATION 	2
#define DISKFULL			3
#define ILLEGALOP			4
#define UNKNOWNID			5
#define FILEEXISTS			6
#define NOSUCHUSER			7

class Packet {
protected:
	unsigned short opcode;
public:
	unsigned short get_opcode() { return opcode; }
};

class RRQ_Packet : Packet {
	std::string filename;
	std::string Mode;
public:
	RRQ_Packet(unsigned short _opcode,
			std::string _filename,
			std::string _Mode)
	:filename(_filename), Mode(_Mode) { opcode = _opcode; }
	std::string get_filename() { return filename; }
	std::string get_Mode() { return Mode; }
};

class DATA_Packet : Packet {
	unsigned short block_no;
	std::vector<char> data;
public:
	DATA_Packet(unsigned short _opcode,
			unsigned short _block_no,
			std::vector<char> _data)
	:block_no(_block_no), data(_data) {  opcode = _opcode; }
	unsigned short get_block_no() { return block_no; }
	std::vector<char> get_data() { return data; }
	std::vector<char> to_array();
};

class ACK_Packet : Packet {
	unsigned short block_no;
public:
	ACK_Packet(unsigned short _opcode,
			unsigned short _block_no)
	:block_no(_block_no) {  opcode = _opcode; }
	unsigned short get_block_no() { return block_no; }
};

class ERROR_Packet : Packet {
	unsigned short ErrorCode;
	std::string ErrMsg;
public:
	ERROR_Packet(unsigned short _opcode,
	unsigned short _ErrorCode,
	std::string _ErrMsg)
	:ErrorCode(_ErrorCode), ErrMsg(_ErrMsg) {  opcode = _opcode; }
	unsigned short get_ErrorCode() { return ErrorCode; }
	std::string get_ErrMsg() { return ErrMsg; }
	std::vector<char> to_array();
};

Packet * generate_packet(std::vector<char> data);
